標記(Label)在機器學習中是十分重要的。機器學習中的模型不會平白無故知道你想要他做什麼,你必須要明確告訴模型你的期望,模型才有辦法幫你找到可以擬合的函數。
模型的兩大方向分別可以導出兩大標記種類:
很多人會直覺反應認為應該使用數值預測的方式,因為這樣可以明確知道未來某時間的成交金額等等。但是這樣有幾個問題以下我們慢慢說明:
這樣來看莫非就沒辦法利用AI賺錢錢嗎?
別灰心可以的。我們看到分類方法的部分,分類模型本身因為他是把不同的交易時機給變成類別,你可以把你的問題簡化成漲跌或不漲不跌、買或不買等等的因素,這時候因為就會減少雜訊的出現而可以收斂,並且因為他是"面向決策"的分析模型,所以可以直接輸出使用(買或是賣)。
在今天的Case中,我們就採用分類模型吧!
AI不像是人類,通常AI做一件單一、簡單的事情可以做得很好,就像其他不是AI的後端邏輯演算法,但是要AI能夠成為一個"通才"是不容易的。原因是因為AI是在擬合一個現實存在的函數的解,X+1=Y這個函數很簡單,但是當函數複雜起來的時候要找到它的解去擬合就變得十分困難。
股市交易可以拆解成兩件事情組成,漲或跌、買或賣多少(不交易就是0),這兩件事情我們可以將它分開來做。分別訓練一個模型預測漲或跌或中立、另一個模型預測交易或不交易。這樣可以簡化很多問題,讓最後模型的結果可以直接應用到程式中輔助交易。
訓練漲跌的我之後叫他方向標籤、是否交易的叫做交易標籤。因為交易標籤必須要在方向標籤已經有的狀態下才去做討論所以現在先略過。
方向的部分首先可以定義一個時間,讓我們模型預測在這個時間內,交易是否會上漲或下跌到一個程度。因為目前資料是日K線,因此我們可以設定為十個交易日的波段比較合適,經驗上這是一個不長度短的時間。
接著我們要定義一下上漲與下跌要多少才算是有漲或跌而不是只有雜訊在震盪。這裡我提出兩種方法,一個是根據經驗設定一個數值,並且調整數值到上漲、下跌、中立三者數量都相同的狀態,另外一個方法是根據過去幾根K棒的標準差去估計震盪大小,取一倍或兩倍標準差作為上漲或下跌的標準。
這之中分別有一些眉角:
這次我們就先用比較難一些的兩倍標準差作為我們上漲下跌的依據吧。
我們先新增兩個欄位為日期前10日最高價的標準差以及日期前10日最低價的標準差
def compute_rolling_std(series):
"""
計算給定序列的滾動標準差。
若資料點不足,則回傳 None。
"""
if len(series) < 10:
return [None] * len(series)
else:
return series.rolling(window=10).std()
# 為每個股票代碼分別計算滾動標準差
data['前10日最高價標準差'] = data.groupby('股票代號')['最高價'].transform(compute_rolling_std)
data['前10日最低價標準差'] = data.groupby('股票代號')['最低價'].transform(compute_rolling_std)
製作兩個標準差的數值欄位
data['最高價+2倍標準差'] = data['前10日最高價標準差'] * 2 + data['最高價']
data['最低價-2倍標準差'] = data['最低價'] - data['前10日最低價標準差'] * 2
計算label,10日以內只要有一次"最高價"大於"最高價+2倍標準差"則記為1反之為-1都沒有就是0
def rolling_window_labeling_updated(group):
labels = np.zeros(len(group))
# 找出未來10天的最高價是否大於「最高價+2倍標準差」
future_max_cond = group['最高價'].rolling(window=10, min_periods=1).max().shift(-10) > group['最高價+2倍標準差']
# 找出未來10天的最低價是否小於「最低價-2倍標準差」
future_min_cond = group['最低價'].rolling(window=10, min_periods=1).min().shift(-10) < group['最低價-2倍標準差']
# 標籤滿足最高價條件的資料為1
labels[future_max_cond] = 1
# 標籤滿足最低價條件的資料為-1
labels[future_min_cond] = -1
# 處理NaN
nan_mask = group['前10日最高價標準差'].isna() | group['前10日最低價標準差'].isna()
labels[nan_mask] = np.nan
# 使用 group 的index回傳 Series
return pd.Series(labels, index=group.index)
# 根據股票代號分組並應用函數
data['label'] = data.groupby('股票代號').apply(rolling_window_labeling_updated).reset_index(level=0, drop=True)
print(data.head(50))
今天先寫到這裡,明天來聊聊特徵建立的部分。
可以參考篇文章:連結
價格發現是期貨市場上供需雙方公開討價還價,通過激烈競爭,使商品價格水平不斷更新,並且不斷向全世界傳播,從而使該商品價格成為世界價格的過程。簡單地説,價格發現就是發現競爭性價格、世界性價格的過程。
引用自百度
回報 連結失效
落後數值:機器學習是一個藉由梯度來調整函數的一個演算法,因此經過實驗會發現模型會一直落後股市反應,形成一個偏移的重影,可以以這個為例,大致會形成以下這張圖,可以看到機器學習預測的曲線轉折都落後時機的線圖:
可以以這個為例 這個 連結失效 [2024-07-15 Mon 14:40]